#include "preHeader.h"
#include "ServerService.h"
#include "Session/GameServerMgr.h"

IServerService::IServerService(const std::string& name)
: m_name(name)
{
}

IServerService::~IServerService()
{
	Packet packet;
	while (m_PacketStorage.Dequeue(packet)) {
		SAFE_DELETE(packet.pck);
	}
}

IServerService::Packet IServerService::NewClientPacket(uint32 uid, INetPacket* pck)
{
	Packet packet;
	packet.type = Packet::Client;
	packet.uid = uid;
	packet.pck = pck;
	return packet;
}

IServerService::Packet IServerService::NewServerPacket(INetPacket* pck)
{
	Packet packet;
	packet.type = Packet::Server;
	packet.pck = pck;
	return packet;
}

void IServerService::PushRecvPacket(const Packet& packet)
{
	m_PacketStorage.Enqueue(packet);
}

void IServerService::UpdateAllPackets()
{
    uint32 opcode = OPCODE_NONE;
	Packet packet;
    TRY_BEGIN {

		while (m_PacketStorage.Dequeue(packet)) {
			opcode = packet.pck->GetOpcode();
			switch (HandleOneRecvPacket(packet)) {
			case SessionHandleCapture:
				break;
			default:
				SAFE_DELETE(packet.pck);
				break;
			}
		}

	} TRY_END
	CATCH_BEGIN(const IException &e) {
		WLOG("`%s` Handle packet opcode[%u] exception occurred.",
			m_name.c_str(), opcode);
		e.Print();
	} CATCH_END
	CATCH_BEGIN(...) {
		WLOG("`%s` Handle packet opcode[%u] unknown exception occurred.",
			m_name.c_str(), opcode);
	} CATCH_END
}

int IServerService::HandleOneRecvPacket(const Packet& packet)
{
	switch (packet.type) {
	case Packet::Client:
		return HandleOneRecvClientPacket(packet);
	case Packet::Server:
		return HandleOneRecvServerPacket(packet);
	default:
		assert(false && "can't reach here.");
		return SessionHandleUnhandle;
	}
}

int IServerService::HandleOneRecvClientPacket(const Packet& packet)
{
	auto opcode = packet.pck->GetOpcode();
	TRY_BEGIN {

		auto retCode = HandleClientPacket(packet.uid, *packet.pck);
		switch (retCode) {
		case SessionHandleSuccess:
			break;
		case SessionHandleCapture:
			break;
		case SessionHandleUnhandle:
			WLOG("`%s` SessionHandleUnhandle Player(%u) Opcode[%u].",
				m_name.c_str(), packet.uid, opcode);
			break;
		case SessionHandleWarning:
			WLOG("`%s` Handle Player(%u) Opcode[%u] Warning!",
				m_name.c_str(), packet.uid, opcode);
			break;
		case SessionHandleError:
			WLOG("`%s` Handle Player(%u) Opcode[%u] Error!",
				m_name.c_str(), packet.uid, opcode);
			break;
		case SessionHandleKill:
		default:
			WLOG("`%s` Fatal error occurred when processing player(%u) opcode[%u], "
				"the player has been removed.", m_name.c_str(), packet.uid, opcode);
			sGameServerMgr.KickPlayer(packet.uid, SessionKickNetPacketError);
			break;
		}
		return retCode != SessionHandleCapture ? SessionHandleSuccess : SessionHandleCapture;

	} TRY_END
	CATCH_BEGIN(const IException &e) {
		WLOG("`%s` Handle packet player(%u) opcode[%u] exception occurred.",
			m_name.c_str(), packet.uid, opcode);
		e.Print();
		sGameServerMgr.KickPlayer(packet.uid, SessionKickNetPacketError);
	} CATCH_END
	CATCH_BEGIN(...) {
		WLOG("`%s` Handle packet player(%u) opcode[%u] unknown exception occurred.",
			m_name.c_str(), packet.uid, opcode);
		sGameServerMgr.KickPlayer(packet.uid, SessionKickNetPacketError);
	} CATCH_END

	return SessionHandleSuccess;
}

int IServerService::HandleOneRecvServerPacket(const Packet& packet)
{
	auto opcode = packet.pck->GetOpcode();
	auto retCode = HandleServerPacket(*packet.pck);
	switch (retCode) {
	case SessionHandleSuccess:
		break;
	case SessionHandleCapture:
		break;
	case SessionHandleUnhandle:
		WLOG("`%s` SessionHandleUnhandle Opcode[%u].", m_name.c_str(), opcode);
		break;
	case SessionHandleWarning:
		WLOG("`%s` Handle Opcode[%u] Warning!", m_name.c_str(), opcode);
		break;
	case SessionHandleError:
		WLOG("`%s` Handle Opcode[%u] Error!", m_name.c_str(), opcode);
		break;
	case SessionHandleKill:
	default:
		WLOG("`%s` Fatal error occurred when processing opcode[%u].", m_name.c_str(), opcode);
		break;
	}
	return retCode != SessionHandleCapture ? SessionHandleSuccess : SessionHandleCapture;
}
